// 声明当前 Java 文件所属的包路径
package com.miku.springaialibabalearn.controller;

// 导入 Spring AI 相关的类
import com.miku.springaialibabalearn.entity.SingerSongs; // 导入 SingerSongs 实体类。注意：在此控制器中并未实际使用此实体类。
import org.springframework.ai.chat.client.ChatClient; // 导入 ChatClient 类。注意：在此控制器中并未实际使用 ChatClient，而是直接使用了 ChatModel。
import org.springframework.ai.chat.model.ChatModel; // 导入 ChatModel 接口，代表一个聊天模型，通常通过依赖注入获取其具体实现。
import org.springframework.ai.chat.model.ChatResponse; // 导入 ChatResponse 类，封装了 AI 模型的响应结果。
import org.springframework.ai.chat.prompt.Prompt; // 导入 Prompt 类，用于封装发送给 AI 模型的输入文本和可选的聊天历史、系统消息等。
import org.springframework.beans.factory.annotation.Qualifier; // 导入 @Qualifier 注解，用于在有多个相同类型的 Bean 时指定注入哪一个。
import org.springframework.http.MediaType; // 导入 MediaType 类，用于指定 HTTP 请求或响应的内容类型。注意：在此控制器中并未实际使用其常量。
// 导入 Spring Web 相关的注解
import org.springframework.web.bind.annotation.*; // 导入所有 Spring Web 的注解，包括 @RestController, @RequestMapping, @CrossOrigin, @GetMapping, @RequestParam 等。
import reactor.core.publisher.Flux; // 导入 Reactor 框架的 Flux 类，用于处理异步流数据。注意：在此控制器中并未实际使用 Flux。

// @RestController 注解：
// 这是一个组合注解，等同于 @Controller 和 @ResponseBody。
// @Controller 标记这是一个 Spring MVC 控制器，用于处理 Web 请求。
// @ResponseBody 标记类中所有方法的返回值都应直接作为 HTTP 响应体发送，而不是解析为视图名称。
@RestController
// @RequestMapping("/deepseek") 注解：
// 标记这个控制器处理所有以 "/deepseek" 为前缀的 URL 请求。
// 例如，如果类中的方法映射到 "/chat"，那么完整的访问路径将是 "/deepseek/chat"。
@RequestMapping("/deepseek")
// @CrossOrigin 注解：
// 启用跨域资源共享 (CORS)。
// origins = "http://localhost:5173" 指定只允许来自 "http://localhost:5173" 这个源（通常是前端应用的地址）的请求访问此控制器。
// 这对于前后端分离开发非常有用，避免浏览器因同源策略而阻止请求。
@CrossOrigin(origins = "http://localhost:5173")
public class DeepSeekChatModelController { // 定义一个名为 DeepSeekChatModelController 的公共类

    // 声明一个私有的 final 字段 deepSeekChatModel，类型为 ChatModel。
    // final 关键字表示这个字段只能被赋值一次，通常在构造函数中。
    // 它将持有通过依赖注入获取的 ChatModel 实例。
    private final ChatModel deepSeekChatModel;

    // 构造函数：
    // Spring 会自动检测到这个构造函数，并通过依赖注入 (DI) 机制查找一个类型为 ChatModel 的 Bean。
    // @Autowired 注解可以省略，因为 Spring 4.3+ 版本如果类只有一个构造函数，会自动进行依赖注入。
    public DeepSeekChatModelController (
            // @Qualifier("openAiChatModel") 注解：
            // 当 Spring 容器中有多个类型为 ChatModel 的 Bean 时，使用 @Qualifier 注解指定要注入的 Bean 的名称。
            // 这里指定注入名称为 "openAiChatModel" 的 ChatModel Bean。
            // 注意：虽然类名是 DeepSeekChatModelController，但这里注入的是 openAiChatModel。
            // 这意味着这个控制器实际上是使用 OpenAI 模型进行交互的，尽管路径前缀是 "/deepseek"。
            // 如果你希望使用 DeepSeek 模型，这里应该注入 DeepSeek 的 ChatModel Bean，并确保其 Bean 名称正确。
            @Qualifier("openAiChatModel") ChatModel chatModel
    ) {
        // 将注入的 ChatModel 实例赋值给类的 deepSeekChatModel 字段。
        this.deepSeekChatModel = chatModel;
    }

    // @GetMapping("/chat") 注解：
    // 标记这个方法处理相对于类级别路径 ("/deepseek") 的 "/chat" 路径的 GET 请求。
    // 完整的访问路径将是 "/deepseek/chat"。
    @GetMapping("/chat")
    // 定义一个公共方法 chat，它接收一个 String 类型的参数 input，并返回一个 String。
    // @RequestParam 注解：
    // 标记 input 参数应从请求参数中获取。
    // 默认情况下，@RequestParam 会查找与参数名 ("input") 相同的请求参数（例如 URL 查询参数 ?input=... 或 POST 请求体中的表单数据）。
    // 如果请求中没有名为 "input" 的参数，且 @RequestParam 没有设置 required = false，则会抛出异常。
    public String chat(@RequestParam String input) {
        // 创建一个 Prompt 对象，将接收到的 input 字符串作为用户消息内容。
        // Prompt 是 Spring AI 中用于封装发送给 AI 模型输入的核心类。
        Prompt prompt = new Prompt(input);
        // 调用注入的 deepSeekChatModel 的 call 方法，将 Prompt 对象发送给 AI 模型。
        // call 方法是 ChatModel 接口的核心方法，用于同步地与 AI 模型进行交互并获取响应。
        // call 方法会阻塞当前线程，直到收到 AI 的响应。
        ChatResponse response = deepSeekChatModel.call(prompt);
        // 从 ChatResponse 对象中获取结果。
        // getResult() 返回一个 Generation 对象，代表 AI 生成的单个响应。
        // getOutput() 从 Generation 对象中获取 ChatOutput 对象，包含 AI 生成的文本内容。
        // getText() 从 ChatOutput 对象中获取 AI 生成的原始文本内容。
        // toString() 也可以用于获取文本内容，但 getContent() 或 getText() 通常更直接。

        // return response.getResult().getOutput().toString(); // 之前使用的 toString() 方法

        // 返回 AI 生成的响应文本字符串。
        return response.getResult().getOutput().getText();
        // 使用 getText() 方法获取文本内容
    }

    // 注意：
    // 1. 这个控制器注入的是 "openAiChatModel"，但类名和 @RequestMapping 路径是 "deepseek"。
    //    这可能导致混淆。建议类名、路径和注入的模型名称保持一致，或者根据实际使用的模型调整。
    // 2. chat 方法现在处理 GET 请求。如果 AI API 期望 POST 请求，你需要将 @GetMapping("/chat") 改为 @PostMapping("/chat")，
    //    并确保客户端发送的是 POST 请求。
    // 3. 导入的 SingerSongs, ChatClient, Flux 在当前代码片段中未使用，可以考虑移除以保持代码简洁。
}
